﻿using Noke.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Noke.SOA.Service
{
    public class SOAService
    {
        private static SOAService _incident = null;

        private static object _lockobject = new object();

        private Dictionary<string, ControllerType> _controllers = null;

        public Dictionary<string, ControllerType> Controllers
        {
            get { return _controllers; }
        }

        private SOAService() { }

        private string ip = string.Empty;

        private int port = -1;

        public static SOAService GetIncident()
        {
            if (_incident != null)
                return _incident;
            lock (_lockobject)
            {
                if (_incident != null)
                    return _incident;

                _incident = new SOAService();
                _incident.ip = "127.0.0.1";
                _incident.port = Convert.ToInt32(ConfigUtil.GetAppSetting("ServicePort"));
                return _incident;
            }
        }

        public void Start()
        {
            IPEndPoint service = new IPEndPoint(IPAddress.Parse(ip), port);        //本地端地址  
            TcpListener listener = new TcpListener(service);            //建立监听类，并绑定到指定的端地址  
            listener.Start();
            // 开始监听   Server is listening...
            while (true)
            {
                TcpClient remoteClient = listener.AcceptTcpClient();  //等待连接（阻塞） 

                //// 得到包含客户端信息的套接字  
                //Socket client = server.Accept();

                //创建消息服务线程对象  
                ClientThread newclient = new ClientThread(remoteClient.Client);

                //把ClientThread 类的ClientService方法委托给线程  
                Thread newthread = new Thread(new ThreadStart(newclient.ClientService));

                // 启动消息服务线程  
                newthread.Start();

            }
        }

        public void InitService(Type typeOfProgram)
        {
            _controllers = new Dictionary<string, ControllerType>();

            Assembly a = Assembly.GetAssembly(typeOfProgram);
            int i = 0;
            string controllerStr = "Controller";
            foreach (Type t in a.DefinedTypes)
            {
                i = t.Name.IndexOf(controllerStr);
                if (i > 1)
                {
                    ControllerType ctype = new ControllerType();
                    ctype.Controller = t;
                    _controllers.Add(t.Name.Substring(0, i), ctype);
                }
            }
        }

    }


    class ClientThread
    {
        //connections变量表示连接数
        public static int connections = 0;
        public Socket service;

        public ClientThread(Socket clientsocket)
        {
            //service对象接管对消息的控制
            this.service = clientsocket;
        }

        public void ClientService()
        {
            if (service != null)
            {
                connections++;
            }


            byte[] RecvBuf = new byte[(1024 * 1024 * 10)];                 //申请接收缓存；
            int recvBytes = service.Receive(RecvBuf);                           //接受客户发送过来的消息； 
            Dictionary<string, Dictionary<string, object>> requestContent = (Dictionary<string, Dictionary<string, object>>)Util.Bytes2Object(RecvBuf);
            if (requestContent != null && requestContent.Count == 1)
            {
                foreach (string key in requestContent.Keys)
                {
                    byte[] SendBuf = Invoke(key, requestContent[key]);
                    service.Send(SendBuf);     //发送欢迎信息；
                    service.Close();                  //关闭连接； /// 
                    connections--;
                }
            }
        }

        private byte[] Invoke(string uri, Dictionary<string, object> vari)
        {
            Dictionary<string, ControllerType> _controllers = SOAService.GetIncident().Controllers;
            if (_controllers == null)
                return null;

            string[] uriarr = uri.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            if (uriarr.Length != 2)
                return null;

            Type controller = _controllers[uriarr[0]].Controller;
            MethodInfo method = controller.GetMethod(uriarr[1]);

            ParameterInfo[] plist = method.GetParameters();
            object[] parameters = new object[plist.Length];
            for (int i = 0; i < plist.Length; i++)
            {
                ParameterInfo p = plist[i];
                if (vari.ContainsKey(p.Name))
                {
                    parameters[i] = vari[p.Name];
                }
            }



            object obj = Activator.CreateInstance(controller, false);

            foreach (string key in vari.Keys)
            {
                object result = method.Invoke(obj, parameters);
                return Util.Object2Bytes(result);
            }

            return null;
        }

    }

    public class ControllerType
    {
        private Type _Controller = null;
        public Type Controller
        {
            get { return _Controller; }
            set { _Controller = value; }
        }
    }
}
